package com.hulytu.dev2.droid;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.ArrayMap;

import com.hulytu.dev2.Embrace;
import com.hulytu.dev2.Platform;
import com.hulytu.dev2.plugin.EnhancePlugin;

import org.jetbrains.annotations.NotNull;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;

public class Dev2App {

    private static Application app;

    private static boolean debuggable;
    private static boolean loggable;

    private Dev2App() {
    }

    private static final ActivityLifecycleCallback CALLBACK = new ActivityLifecycleCallback();

    public static void init(Context context) {
        init(context, null);
    }

    public static void init(Context context, Embrace embrace) {
        if (context instanceof Application) {
            app = (Application) context;
        } else {
            app = (Application) context.getApplicationContext();
        }

        app.unregisterActivityLifecycleCallbacks(CALLBACK);
        app.registerActivityLifecycleCallbacks(CALLBACK);

        Platform.init(embrace);
    }

    public static Application app() {
        return app;
    }

    public static void setDebuggable(boolean debuggable) {
        Dev2App.debuggable = debuggable;
    }

    public static void setLoggable(boolean loggable) {
        Dev2App.loggable = loggable;
    }

    public static boolean isDebuggable() {
        return debuggable;
    }

    public static boolean isLoggable() {
        return loggable;
    }

    static class ActivityLifecycleCallback implements Application.ActivityLifecycleCallbacks {
        private final Map<String, Method> lifecycleMethodCache = new ArrayMap<>();

        ActivityLifecycleCallback() {

            Class<?> clazz = ActivityEnhancePlugin.class;
            try {

                lifecycleMethodCache.put(ActivityEnhancePlugin.CREATE, clazz.getMethod(ActivityEnhancePlugin.CREATE, Activity.class, Bundle.class));

                String[] array = {
                        ActivityEnhancePlugin.RESUME,
                        ActivityEnhancePlugin.STOP,
                        ActivityEnhancePlugin.PAUSE,
                        ActivityEnhancePlugin.START,
                        ActivityEnhancePlugin.DESTROY,
                };

                for (String s : array) {
                    lifecycleMethodCache.put(s, clazz.getMethod(s, Activity.class));
                }

                Collection<Method> methods = lifecycleMethodCache.values();
                for (Method method : methods) {
                    method.setAccessible(true);
                }

            } catch (Exception ignore) {
            }
        }

        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            onActivityLifecycleCallback(ActivityEnhancePlugin.CREATE, activity, savedInstanceState);
        }

        @Override
        public void onActivityStarted(Activity activity) {
            onActivityLifecycleCallback(ActivityEnhancePlugin.START, activity);
        }

        @Override
        public void onActivityResumed(Activity activity) {
            onActivityLifecycleCallback(ActivityEnhancePlugin.RESUME, activity);
        }

        @Override
        public void onActivityPaused(Activity activity) {
            onActivityLifecycleCallback(ActivityEnhancePlugin.PAUSE, activity);
        }

        @Override
        public void onActivityStopped(Activity activity) {
            onActivityLifecycleCallback(ActivityEnhancePlugin.STOP, activity);
        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

        }

        @Override
        public void onActivityDestroyed(Activity activity) {
            onActivityLifecycleCallback(ActivityEnhancePlugin.DESTROY, activity);
        }

        private void onActivityLifecycleCallback(String name, Object... args) {

            Method method;
            if (args.length < 1 || (method = lifecycleMethodCache.get(name)) == null)
                return;

            Embrace embrace = Platform.get();

            for (EnhancePlugin plugin : embrace.plugins()) {
                if (plugin instanceof ActivityEnhancePlugin) {
                    lifecycle(method, (ActivityEnhancePlugin<?>) plugin, args);
                }
            }
        }

        private void lifecycle(@NotNull Method method, ActivityEnhancePlugin<?> plugin, Object... args) {
            Activity activity = plugin.getActivity();

            Object arg0 = args[0];
            if (arg0 != activity) return;

            try {
                method.invoke(plugin, args);
            } catch (Exception ignore) {
            }
        }

    }
}
